&options.flag_test,
&options.flag_example,
&options.flag_bench),
+ extra_rustdoc_args: Vec::new(),
target_rustc_args: None,
},
};
&options.flag_test,
&options.flag_example,
&options.flag_bench),
+ extra_rustdoc_args: Vec::new(),
target_rustc_args: None,
};
$mac!(read_manifest);
$mac!(run);
$mac!(rustc);
+ $mac!(rustdoc);
$mac!(search);
$mac!(test);
$mac!(uninstall);
deps: !options.flag_no_deps,
},
target_rustc_args: None,
+ extra_rustdoc_args: Vec::new(),
},
};
bins: &bins, examples: &examples,
}
},
+ extra_rustdoc_args: Vec::new(),
target_rustc_args: None,
};
&options.flag_test,
&options.flag_example,
&options.flag_bench),
+ extra_rustdoc_args: Vec::new(),
target_rustc_args: options.arg_opts.as_ref().map(|a| &a[..]),
};
--- /dev/null
+use cargo::ops;
+use cargo::util::{CliResult, CliError, Config};
+use cargo::util::important_paths::{find_root_manifest_for_cwd};
+
+#[derive(RustcDecodable)]
+struct Options {
+ arg_opts: Vec<String>,
+ flag_target: Option<String>,
+ flag_features: Vec<String>,
+ flag_jobs: Option<u32>,
+ flag_manifest_path: Option<String>,
+ flag_no_default_features: bool,
+ flag_no_deps: bool,
+ flag_open: bool,
+ flag_verbose: bool,
+ flag_release: bool,
+ flag_quiet: bool,
+ flag_color: Option<String>,
+ flag_package: Option<String>,
+}
+
+pub const USAGE: &'static str = "
+Build a package's documentation, using specified custom flags.
+
+Usage:
+ cargo rustdoc [options] [--] [<opts>...]
+
+Options:
+ -h, --help Print this message
+ --open Opens the docs in a browser after the operation
+ -p SPEC, --package SPEC Package to document
+ --no-deps Don't build documentation for dependencies
+ -j N, --jobs N The number of jobs to run in parallel
+ --release Build artifacts in release mode, with optimizations
+ --features FEATURES Space-separated list of features to also build
+ --no-default-features Do not build the `default` feature
+ --target TRIPLE Build for the target triple
+ --manifest-path PATH Path to the manifest to document
+ -v, --verbose Use verbose output
+ -q, --quiet No output printed to stdout
+ --color WHEN Coloring: auto, always, never
+
+By default the documentation for the local package and all dependencies is
+built. The output is all placed in `target/doc` in rustdoc's usual format.
+
+The specified target for the current package (or package specified by SPEC if
+provided) will be documented along with all of its dependencies. The specified
+<opts>... will all be passed to the final rustdoc invocation, not any of the
+dependencies. Note that rustdoc will still unconditionally receive
+arguments such as -L, --extern, and --crate-type, and the specified <opts>...
+will simply be added to the rustdoc invocation.
+
+If the --package argument is given, then SPEC is a package id specification
+which indicates which package should be documented. If it is not given, then the
+current package is documented. For more information on SPEC and its format, see
+the `cargo help pkgid` command.
+";
+
+pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
+ try!(config.shell().set_verbosity(options.flag_verbose, options.flag_quiet));
+ try!(config.shell().set_color_config(options.flag_color.as_ref().map(|s| &s[..])));
+
+ let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));
+
+ let mut doc_opts = ops::DocOptions {
+ open_result: options.flag_open,
+ compile_opts: ops::CompileOptions {
+ config: config,
+ jobs: options.flag_jobs,
+ target: options.flag_target.as_ref().map(|t| &t[..]),
+ features: &options.flag_features,
+ no_default_features: options.flag_no_default_features,
+ spec: options.flag_package.as_ref().map(|s| &s[..]),
+ exec_engine: None,
+ filter: ops::CompileFilter::Everything,
+ release: options.flag_release,
+ mode: ops::CompileMode::Doc {
+ deps: !options.flag_no_deps,
+ },
+ extra_rustdoc_args: options.arg_opts,
+ target_rustc_args: None,
+ },
+ };
+
+ try!(ops::doc(&root, &mut doc_opts).map_err(|err| CliError::from_boxed(err, 101)));
+
+ Ok(None)
+}
+
&options.flag_test,
&options.flag_example,
&options.flag_bench),
+ extra_rustdoc_args: Vec::new(),
target_rustc_args: None,
},
};
pub lto: bool,
pub codegen_units: Option<u32>, // None = use rustc default
pub rustc_args: Option<Vec<String>>,
+ pub rustdoc_args: Option<Vec<String>>,
pub debuginfo: bool,
pub debug_assertions: bool,
pub rpath: bool,
lto: false,
codegen_units: None,
rustc_args: None,
+ rustdoc_args: None,
debuginfo: false,
debug_assertions: false,
rpath: false,
pub release: bool,
/// Mode for this compile.
pub mode: CompileMode,
+ /// Extra arguments to be passed to rustdoc (for main crate and dependencies)
+ pub extra_rustdoc_args: Vec<String>,
/// The specified target will be compiled with all the available arguments,
/// note that this only accounts for the *final* invocation of rustc
pub target_rustc_args: Option<&'a [String]>,
let CompileOptions { config, jobs, target, spec, features,
no_default_features, release, mode,
ref filter, ref exec_engine,
+ ref extra_rustdoc_args,
ref target_rustc_args } = *options;
let target = target.map(|s| s.to_string());
}
let mut ret = {
+ let mut target_with_rustdoc = None;
+ if !extra_rustdoc_args.is_empty() {
+ let mut target_with_rustdoc_inner = Vec::new();
+ for &(target, profile) in &targets {
+ if profile.doc {
+ let mut profile = profile.clone();
+ profile.rustdoc_args = Some(extra_rustdoc_args.clone());
+ target_with_rustdoc_inner.push((target, profile));
+ }
+ }
+ target_with_rustdoc = Some(target_with_rustdoc_inner);
+ };
+
+ let targets = target_with_rustdoc.as_ref().map_or(targets,
+ |o| o.into_iter()
+ .map(|&(t, ref p)| (t, p))
+ .collect());
+ let ret = {
let _p = profile::start("compiling");
let mut build_config = try!(scrape_build_config(config, jobs, target));
build_config.exec_engine = exec_engine.clone();
exec_engine: None,
release: false,
mode: ops::CompileMode::Build,
+ extra_rustdoc_args: Vec::new(),
target_rustc_args: None,
}));
}
}
+ if let Some(ref args) = profile.rustdoc_args {
+ rustdoc.args(args);
+ }
+
try!(build_deps_args(&mut rustdoc, cx, unit));
if unit.pkg.has_custom_build() {
let Profile {
opt_level, lto, codegen_units, ref rustc_args, debuginfo,
debug_assertions, rpath, test, doc: _doc, run_custom_build,
+ rustdoc_args: _,
} = *unit.profile;
assert!(!run_custom_build);
lto: lto.unwrap_or(profile.lto),
codegen_units: codegen_units,
rustc_args: None,
+ rustdoc_args: None,
debuginfo: debug.unwrap_or(profile.debuginfo),
debug_assertions: debug_assertions.unwrap_or(profile.debug_assertions),
rpath: rpath.unwrap_or(profile.rpath),
--- /dev/null
+use std::path::MAIN_SEPARATOR as SEP;
+use support::{execs, project};
+use support::{COMPILING, RUNNING};
+use hamcrest::{assert_that};
+
+fn setup() {
+}
+
+
+test!(rustdoc_simple {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#" "#);
+
+ assert_that(p.cargo_process("rustdoc").arg("-v"),
+ execs()
+ .with_status(0)
+ .with_stdout(format!("\
+{compiling} foo v0.0.1 ({url})
+{running} `rustdoc src{sep}lib.rs --crate-name foo \
+ -o {dir}{sep}target{sep}doc \
+ -L dependency={dir}{sep}target{sep}debug \
+ -L dependency={dir}{sep}target{sep}debug{sep}deps`
+",
+ running = RUNNING, compiling = COMPILING, sep = SEP,
+ dir = p.root().display(), url = p.url())));
+});
+
+test!(rustdoc_args {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#" "#);
+
+ assert_that(p.cargo_process("rustdoc").arg("-v").arg("--").arg("--no-defaults"),
+ execs()
+ .with_status(0)
+ .with_stdout(format!("\
+{compiling} foo v0.0.1 ({url})
+{running} `rustdoc src{sep}lib.rs --crate-name foo \
+ -o {dir}{sep}target{sep}doc \
+ --no-defaults \
+ -L dependency={dir}{sep}target{sep}debug \
+ -L dependency={dir}{sep}target{sep}debug{sep}deps`
+",
+ running = RUNNING, compiling = COMPILING, sep = SEP,
+ dir = p.root().display(), url = p.url())));
+});
+
+
+
+test!(rustdoc_foo_with_bar_dependency {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate bar;
+ pub fn foo() {}
+ "#);
+ let bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#);
+ bar.build();
+
+ assert_that(foo.cargo_process("rustdoc").arg("-v").arg("--").arg("--no-defaults"),
+ execs()
+ .with_status(0)
+ .with_stdout(format!("\
+{compiling} bar v0.0.1 ({url})
+{running} `rustc {bar_dir}{sep}src{sep}lib.rs [..]`
+{running} `rustdoc {bar_dir}{sep}src{sep}lib.rs --crate-name bar \
+ -o {dir}{sep}target{sep}doc \
+ -L dependency={dir}{sep}target{sep}debug{sep}deps \
+ -L dependency={dir}{sep}target{sep}debug{sep}deps`
+{compiling} foo v0.0.1 ({url})
+{running} `rustdoc src{sep}lib.rs --crate-name foo \
+ -o {dir}{sep}target{sep}doc \
+ --no-defaults \
+ -L dependency={dir}{sep}target{sep}debug \
+ -L dependency={dir}{sep}target{sep}debug{sep}deps \
+ --extern [..]`
+",
+ running = RUNNING, compiling = COMPILING, sep = SEP,
+ dir = foo.root().display(), url = foo.url(),
+ bar_dir = bar.root().display())));
+});
+
+test!(rustdoc_only_bar_dependency {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ bar::baz()
+ }
+ "#);
+ let bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#);
+ bar.build();
+
+ assert_that(foo.cargo_process("rustdoc").arg("-v").arg("-p").arg("bar")
+ .arg("--").arg("--no-defaults"),
+ execs()
+ .with_status(0)
+ .with_stdout(format!("\
+{compiling} bar v0.0.1 ({url})
+{running} `rustdoc {bar_dir}{sep}src{sep}lib.rs --crate-name bar \
+ -o {dir}{sep}target{sep}doc \
+ --no-defaults \
+ -L dependency={dir}{sep}target{sep}debug{sep}deps \
+ -L dependency={dir}{sep}target{sep}debug{sep}deps`
+",
+ running = RUNNING, compiling = COMPILING, sep = SEP,
+ dir = foo.root().display(), url = foo.url(),
+ bar_dir = bar.root().display())));
+});
+
+
+test!(rustdoc_same_name_err {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#);
+
+ assert_that(p.cargo_process("rustdoc").arg("-v")
+ .arg("--").arg("--no-defaults"),
+ execs()
+ .with_status(101)
+ .with_stderr("Cannot document a package where a library and a \
+ binary have the same name. Consider renaming one \
+ or marking the target as `doc = false`"));
+});
mod test_cargo_registry;
mod test_cargo_run;
mod test_cargo_rustc;
+mod test_cargo_rustdoc;
mod test_cargo_search;
mod test_cargo_test;
mod test_cargo_tool_paths;